﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Windows.Forms;
using System.Reflection;

using Sintaxe;
using Sintaxe.Instrucoes;

/*
 * Oferece uma lista de processadores utilizaveis com o software J5
 * Adicionar um novo processador necesita:
 * - Colocar ele com todas as classes requeridas em um novo project na soltion processors
 * - adicionar uma referência ao este project para project montador
 *   (no desenvolvimento, manualmente. Mais tarde talvez GAC)
 *   - adicionar mais um item na inicialização aqui.
 *   
 * O Portfolio é um Singleton.
 * Portfolio forneçe acesso aos tipos e objetos. Não é sempre possivel fazer isso baseado 
 * no nome de tipo de processador, por que Activator.CreateInstance precisa nome de assembly tambem.
 * Esta informação é centralizado aqui
 * 
 */


namespace Montador
{
    public static class Portfolio
    {
        private static bool Inicializado = false;
        private static DataTable POF;
        // LAB4A1 usa este caminho:
        private static string AssemblyPath = @"C:\Users\thomas.jeffre\Documents\J4 Development\Step001\Processors-Step001\XYSC-1\bin\Debug\";
        // Voyager usa este caminho:
        //private static string AssemblyPath = @"C:\J4 Development\Step001\Processors-Step001\XYSC-1\bin\Debug\";

        private static void Ini()
        {
            // instanciar e encher a tabela de Portfolio
            DataRow rr;

            if (Inicializado) return;  // uma das muuuuitas estrategias a realizar um Singleton

            POF = new DataTable();
            POF.Columns.Add(new DataColumn("Assy", typeof(string)));
            POF.Columns.Add(new DataColumn("NSpace", typeof(string)));  //  namespace
            POF.Columns.Add(new DataColumn("Proc", typeof(string)));
            POF.Columns.Add(new DataColumn("Form", typeof(string)));
            POF.Columns.Add(new DataColumn("Inst", typeof(string)));

            // colocar a informação sobre XYSC1_V2
            rr = POF.NewRow();
            rr["Assy"] = "XYSC-1";
            rr["NSpace"] = "XYSC_1";
            rr["Proc"] = "XYSC1_V2";
            rr["Form"] = "frmEditXYSC1";
            rr["Inst"] = "IM_XYSC1_V2";
            POF.Rows.Add(rr);
        }
        private static DataRow Configuracao(string strTipo)
        {
            // devolve uma data row com os dados do processor com strTipo.
            // Lanca exceção se não tem exatemente um

            Ini();
            DataRow[] rrr = POF.Select("Proc = '" + strTipo + "'");
            if (rrr.Length == 0) throw new ApplicationException("Não tem Processador " + strTipo);
            if (rrr.Length > 1) throw new ApplicationException("Tem mais do que 1 Processador " + strTipo);
            return rrr[0];
        }
        public static IProcessador objProc(string strTipo)
        {
            Ini();

            DataRow rr = Configuracao(strTipo);
            string strAssy = (string)rr["Assy"];
            string strNS = (string)rr["NSpace"];
            string strPath = AssemblyPath + strAssy + ".dll";

            Assembly aa = Assembly.LoadFrom(strPath);
            IProcessador pp = (IProcessador)aa.CreateInstance(strNS + "." + strTipo);
            return pp;
        }
        public static Type tyInst(string strTipo)
        {
            Ini();

            DataRow rr = Configuracao(strTipo);
            string strAssy = (string)rr["Assy"];
            string strPath = AssemblyPath + strAssy + ".dll";
            string strNS = (string)rr["NSpace"];
            string strInst = (string)rr["Inst"];

            Assembly aa = Assembly.LoadFrom(strPath);
            Type tt = aa.GetType(strNS + "." + strInst);
            return tt;
        }
        public static Instrucao objInst(string strTipo)
        {
            Ini();
            DataRow rr = Configuracao(strTipo);
            string strAssy = (string)rr["Assy"];
            string strPath = AssemblyPath + strAssy + ".dll";
            string strNS = (string)rr["NSpace"];
            string strInst = (string)rr["Inst"];

            Assembly aa = Assembly.LoadFrom(strPath);
            Instrucao ii = (Instrucao)aa.CreateInstance(strNS + "." + strInst);
            return ii;
        }
        public static Instrucao objInst(string strTipo, object[] prmArgs)
        {
            Ini();
            Type tt = tyInst(strTipo);
            Instrucao ii = (Instrucao)Activator.CreateInstance(tt, prmArgs);
            return ii;
        }
        public static Type tyForm(string strTipo)
        {
            Ini();

            DataRow rr = Configuracao(strTipo);
            string strAssy = (string)rr["Assy"];
            string strPath = AssemblyPath + strAssy + ".dll";
            string strNS = (string)rr["NSpace"];
            string strForm = (string)rr["Form"];

            Assembly aa = Assembly.LoadFrom(strPath);
            Type tt = aa.GetType(strNS + "." + strForm);
            return tt;
        }
        public static Form objForm(string strTipo, object[] prmArgs)
        {
            Ini();
            Type tt = tyForm(strTipo);
            Form ff = (Form)Activator.CreateInstance(tt, prmArgs);
            return ff;
        }
    }
}
